#!/usr/bin/env python3
"""
天气预报集成和环境预测模块
Weather Forecast Integration and Environmental Prediction Module
"""

import random
import json
from datetime import datetime, timedelta
from dataclasses import dataclass
from typing import List, Dict, Any
import numpy as np

@dataclass
class WeatherData:
    """天气数据结构"""
    timestamp: datetime
    temperature: float  # 温度 (°C)
    humidity: float  # 湿度 (%)
    rainfall: float  # 降雨量 (mm)
    wind_speed: float  # 风速 (m/s)
    pressure: float  # 气压 (hPa)
    cloud_cover: float  # 云量 (%)
    uv_index: float  # 紫外线指数
    weather_type: str  # 天气类型

@dataclass
class CropGrowthStage:
    """作物生长阶段"""
    stage_name: str
    days_remaining: int
    water_requirement: float  # 需水量系数
    nutrient_requirement: Dict[str, float]  # 营养需求
    optimal_temperature: tuple  # 最适温度范围
    critical_factors: List[str]  # 关键因素

class WeatherForecastSystem:
    """天气预报系统"""
    
    def __init__(self):
        self.weather_types = [
            "晴天", "多云", "阴天", "小雨", "中雨", "大雨", 
            "雷阵雨", "雾", "霜冻", "高温"
        ]
        
        # 季节性天气模式
        self.seasonal_patterns = {
            'spring': {'temp_range': (15, 25), 'rain_prob': 0.3},
            'summer': {'temp_range': (25, 35), 'rain_prob': 0.4},
            'autumn': {'temp_range': (10, 20), 'rain_prob': 0.2},
            'winter': {'temp_range': (0, 10), 'rain_prob': 0.1}
        }
    
    def get_current_season(self) -> str:
        """获取当前季节"""
        month = datetime.now().month
        if month in [3, 4, 5]:
            return 'spring'
        elif month in [6, 7, 8]:
            return 'summer'
        elif month in [9, 10, 11]:
            return 'autumn'
        else:
            return 'winter'
    
    def generate_weather_forecast(self, days: int = 7) -> List[WeatherData]:
        """生成天气预报"""
        forecast = []
        current_time = datetime.now()
        season = self.get_current_season()
        pattern = self.seasonal_patterns[season]
        
        for i in range(days):
            date = current_time + timedelta(days=i)
            
            # 基于季节模式生成天气数据
            temp_min, temp_max = pattern['temp_range']
            base_temp = random.uniform(temp_min, temp_max)
            
            # 添加日夜温差
            hour_factor = np.sin((date.hour - 6) * np.pi / 12)
            temperature = base_temp + 5 * hour_factor + random.gauss(0, 2)
            
            # 生成其他天气参数
            humidity = np.clip(random.gauss(65, 15), 30, 100)
            
            # 降雨概率和量
            rain_prob = pattern['rain_prob']
            if random.random() < rain_prob:
                rainfall = random.exponential(5)  # 指数分布模拟降雨
            else:
                rainfall = 0
            
            wind_speed = np.clip(random.gauss(3, 2), 0, 15)
            pressure = random.gauss(1013, 10)
            cloud_cover = np.clip(random.gauss(50, 30), 0, 100)
            uv_index = max(0, random.gauss(6, 2))
            
            # 根据条件确定天气类型
            if rainfall > 10:
                weather_type = "大雨"
            elif rainfall > 5:
                weather_type = "中雨"
            elif rainfall > 0:
                weather_type = "小雨"
            elif cloud_cover > 80:
                weather_type = "阴天"
            elif cloud_cover > 40:
                weather_type = "多云"
            else:
                weather_type = "晴天"
            
            # 特殊天气条件
            if temperature < 2 and humidity > 80:
                weather_type = "霜冻"
            elif temperature > 35:
                weather_type = "高温"
            elif humidity > 95 and wind_speed < 1:
                weather_type = "雾"
            
            weather = WeatherData(
                timestamp=date,
                temperature=temperature,
                humidity=humidity,
                rainfall=rainfall,
                wind_speed=wind_speed,
                pressure=pressure,
                cloud_cover=cloud_cover,
                uv_index=uv_index,
                weather_type=weather_type
            )
            
            forecast.append(weather)
        
        return forecast
    
    def predict_environmental_impact(self, forecast: List[WeatherData], 
                                   current_soil_moisture: float) -> Dict[str, Any]:
        """预测环境影响"""
        predictions = {
            'irrigation_needs': [],
            'disease_risks': [],
            'growth_conditions': [],
            'alerts': []
        }
        
        for i, weather in enumerate(forecast):
            day_name = f"第{i+1}天"
            
            # 预测灌溉需求
            expected_moisture_loss = 5 + weather.temperature * 0.3 + weather.wind_speed * 0.5
            moisture_gain = weather.rainfall * 0.8  # 降雨转化为土壤湿度
            
            predicted_moisture = current_soil_moisture - expected_moisture_loss + moisture_gain
            
            if predicted_moisture < 30:
                irrigation_need = "高需求"
                irrigation_amount = max(10, 40 - predicted_moisture)
            elif predicted_moisture < 50:
                irrigation_need = "中等需求"
                irrigation_amount = max(5, 35 - predicted_moisture)
            else:
                irrigation_need = "低需求"
                irrigation_amount = 0
            
            predictions['irrigation_needs'].append({
                'day': day_name,
                'need_level': irrigation_need,
                'recommended_amount': irrigation_amount,
                'predicted_moisture': predicted_moisture
            })
            
            # 预测病虫害风险
            disease_risk = 0
            risk_factors = []
            
            if weather.humidity > 80:
                disease_risk += 0.3
                risk_factors.append("高湿度")
            
            if weather.temperature > 25 and weather.humidity > 70:
                disease_risk += 0.4
                risk_factors.append("高温高湿")
            
            if weather.rainfall > 0 and weather.wind_speed < 2:
                disease_risk += 0.2
                risk_factors.append("降雨+低风速")
            
            if weather.cloud_cover > 80:
                disease_risk += 0.1
                risk_factors.append("阴天")
            
            risk_level = "低"
            if disease_risk > 0.7:
                risk_level = "高"
            elif disease_risk > 0.4:
                risk_level = "中"
            
            predictions['disease_risks'].append({
                'day': day_name,
                'risk_level': risk_level,
                'risk_score': disease_risk,
                'risk_factors': risk_factors
            })
            
            # 评估生长条件
            growth_score = 0
            
            # 温度适宜性 (20-28°C最适宜)
            if 20 <= weather.temperature <= 28:
                growth_score += 0.4
            elif 15 <= weather.temperature <= 32:
                growth_score += 0.2
            
            # 湿度适宜性 (60-80%最适宜)
            if 60 <= weather.humidity <= 80:
                growth_score += 0.3
            elif 50 <= weather.humidity <= 90:
                growth_score += 0.1
            
            # 光照条件
            if weather.cloud_cover < 30:
                growth_score += 0.2
            elif weather.cloud_cover < 60:
                growth_score += 0.1
            
            # 风速适宜性
            if 1 <= weather.wind_speed <= 5:
                growth_score += 0.1
            
            growth_condition = "优秀"
            if growth_score < 0.3:
                growth_condition = "较差"
            elif growth_score < 0.6:
                growth_condition = "一般"
            elif growth_score < 0.8:
                growth_condition = "良好"
            
            predictions['growth_conditions'].append({
                'day': day_name,
                'condition': growth_condition,
                'score': growth_score,
                'temperature': weather.temperature,
                'humidity': weather.humidity
            })
            
            # 生成预警
            alerts = []
            if weather.weather_type == "霜冻":
                alerts.append("⚠️ 霜冻预警：注意作物保温")
            elif weather.weather_type == "高温":
                alerts.append("🌡️ 高温预警：增加遮阳和通风")
            elif weather.rainfall > 15:
                alerts.append("🌧️ 暴雨预警：注意排水防涝")
            elif weather.wind_speed > 10:
                alerts.append("💨 大风预警：检查设施稳固性")
            elif disease_risk > 0.7:
                alerts.append("🦠 病害高风险：建议预防性喷药")
            
            if alerts:
                predictions['alerts'].extend([{
                    'day': day_name,
                    'alerts': alerts
                }])
        
        return predictions

class CropManagementSystem:
    """作物管理系统"""
    
    def __init__(self):
        # 常见作物的生长阶段定义
        self.crop_stages = {
            'tomato': [
                CropGrowthStage("发芽期", 7, 0.3, {"N": 0.5, "P": 0.8, "K": 0.3}, (20, 25), ["温度", "湿度"]),
                CropGrowthStage("苗期", 21, 0.5, {"N": 0.8, "P": 0.6, "K": 0.4}, (18, 28), ["光照", "温度"]),
                CropGrowthStage("开花期", 14, 0.8, {"N": 0.6, "P": 1.0, "K": 0.8}, (20, 26), ["温度", "湿度", "授粉"]),
                CropGrowthStage("结果期", 35, 1.0, {"N": 0.4, "P": 0.8, "K": 1.0}, (22, 28), ["水分", "钾肥"]),
                CropGrowthStage("成熟期", 21, 0.6, {"N": 0.2, "P": 0.4, "K": 0.8}, (20, 26), ["糖分积累"])
            ],
            'lettuce': [
                CropGrowthStage("发芽期", 5, 0.4, {"N": 0.6, "P": 0.8, "K": 0.4}, (15, 20), ["温度", "湿度"]),
                CropGrowthStage("幼苗期", 14, 0.6, {"N": 0.8, "P": 0.6, "K": 0.5}, (12, 22), ["光照", "通风"]),
                CropGrowthStage("快速生长期", 21, 0.9, {"N": 1.0, "P": 0.7, "K": 0.8}, (15, 25), ["氮肥", "水分"]),
                CropGrowthStage("成熟期", 14, 0.5, {"N": 0.6, "P": 0.5, "K": 0.6}, (10, 20), ["品质控制"])
            ]
        }
        
        self.current_crop = 'tomato'
        self.current_stage_index = 1  # 当前处于苗期
        self.planting_date = datetime.now() - timedelta(days=28)
    
    def get_current_stage(self) -> CropGrowthStage:
        """获取当前生长阶段"""
        return self.crop_stages[self.current_crop][self.current_stage_index]
    
    def get_stage_progress(self) -> float:
        """获取当前阶段进度"""
        days_since_planting = (datetime.now() - self.planting_date).days
        
        total_days = 0
        for i, stage in enumerate(self.crop_stages[self.current_crop]):
            if i < self.current_stage_index:
                total_days += stage.days_remaining
            elif i == self.current_stage_index:
                stage_days_passed = days_since_planting - total_days
                return min(stage_days_passed / stage.days_remaining, 1.0)
        
        return 1.0
    
    def get_management_recommendations(self, weather_forecast: List[WeatherData],
                                     current_conditions: Dict) -> Dict[str, Any]:
        """获取管理建议"""
        current_stage = self.get_current_stage()
        progress = self.get_stage_progress()
        
        recommendations = {
            'stage_info': {
                'crop': self.current_crop,
                'current_stage': current_stage.stage_name,
                'progress': f"{progress*100:.1f}%",
                'days_remaining': int(current_stage.days_remaining * (1 - progress)),
                'critical_factors': current_stage.critical_factors
            },
            'irrigation': {},
            'nutrition': {},
            'environmental': {},
            'tasks': []
        }
        
        # 灌溉建议
        base_water_need = current_stage.water_requirement
        
        # 根据天气调整水分需求
        upcoming_rain = sum(w.rainfall for w in weather_forecast[:3])  # 未来3天降雨
        avg_temp = sum(w.temperature for w in weather_forecast[:3]) / 3
        avg_humidity = sum(w.humidity for w in weather_forecast[:3]) / 3
        
        adjusted_water_need = base_water_need
        if upcoming_rain < 5:  # 少雨
            adjusted_water_need *= 1.2
        elif upcoming_rain > 20:  # 多雨
            adjusted_water_need *= 0.7
        
        if avg_temp > 28:  # 高温
            adjusted_water_need *= 1.3
        elif avg_temp < 15:  # 低温
            adjusted_water_need *= 0.8
        
        recommendations['irrigation'] = {
            'base_requirement': base_water_need,
            'adjusted_requirement': adjusted_water_need,
            'frequency': "每日" if adjusted_water_need > 0.8 else "隔日",
            'amount_per_irrigation': f"{adjusted_water_need * 20:.1f}L/m²",
            'timing': "早晨6-8点或傍晚5-7点"
        }
        
        # 营养建议
        nutrients = current_stage.nutrient_requirement
        recommendations['nutrition'] = {
            'nitrogen': f"{nutrients['N']*100:.0f}%基准量",
            'phosphorus': f"{nutrients['P']*100:.0f}%基准量",
            'potassium': f"{nutrients['K']*100:.0f}%基准量",
            'fertilization_schedule': f"每{7 if progress < 0.5 else 14}天施肥一次"
        }
        
        # 环境管理
        temp_min, temp_max = current_stage.optimal_temperature
        recommendations['environmental'] = {
            'optimal_temperature': f"{temp_min}-{temp_max}°C",
            'current_suitability': self._assess_temperature_suitability(
                avg_temp, temp_min, temp_max),
            'humidity_target': "65-75%",
            'ventilation': "适中" if avg_humidity < 80 else "加强通风"
        }
        
        # 任务提醒
        tasks = []
        
        # 基于阶段的任务
        if current_stage.stage_name == "苗期":
            tasks.append("检查幼苗长势，及时间苗")
            tasks.append("注意防治苗期病害")
        elif current_stage.stage_name == "开花期":
            tasks.append("人工辅助授粉")
            tasks.append("控制温湿度促进开花")
        elif current_stage.stage_name == "结果期":
            tasks.append("及时采收成熟果实")
            tasks.append("加强钾肥补充")
        
        # 基于天气的任务
        for weather in weather_forecast[:3]:
            if weather.weather_type == "霜冻":
                tasks.append("准备防霜设施")
            elif weather.weather_type == "高温":
                tasks.append("增加遮阳网覆盖")
            elif weather.rainfall > 15:
                tasks.append("检查排水系统")
        
        recommendations['tasks'] = list(set(tasks))  # 去重
        
        return recommendations
    
    def _assess_temperature_suitability(self, current_temp: float, 
                                      min_temp: float, max_temp: float) -> str:
        """评估温度适宜性"""
        if min_temp <= current_temp <= max_temp:
            return "适宜"
        elif min_temp - 5 <= current_temp <= max_temp + 5:
            return "可接受"
        else:
            return "不适宜"

class AdvancedAnalytics:
    """高级分析系统"""
    
    def __init__(self):
        self.historical_data = []
    
    def predict_yield(self, current_conditions: Dict, management_history: List) -> Dict:
        """产量预测"""
        # 简化的产量预测模型
        base_yield = 100  # 基准产量 (kg/亩)
        
        # 环境因子影响
        temp_factor = 1.0
        if 20 <= current_conditions.get('temperature', 25) <= 28:
            temp_factor = 1.2
        elif current_conditions.get('temperature', 25) > 35:
            temp_factor = 0.7
        
        moisture_factor = 1.0
        soil_moisture = current_conditions.get('soil_moisture', 50)
        if 40 <= soil_moisture <= 70:
            moisture_factor = 1.1
        elif soil_moisture < 25:
            moisture_factor = 0.6
        
        nutrition_factor = 1.0
        ph_value = current_conditions.get('ph_value', 6.5)
        if 6.0 <= ph_value <= 7.0:
            nutrition_factor = 1.1
        
        # 管理因子影响
        management_factor = 1.0
        if len(management_history) > 10:  # 有充足的管理记录
            management_factor = 1.05
        
        predicted_yield = base_yield * temp_factor * moisture_factor * nutrition_factor * management_factor
        
        # 添加不确定性
        confidence = 0.85
        if len(management_history) < 5:
            confidence = 0.70
        
        return {
            'predicted_yield': predicted_yield,
            'confidence': confidence,
            'factors': {
                'temperature': temp_factor,
                'moisture': moisture_factor,
                'nutrition': nutrition_factor,
                'management': management_factor
            },
            'recommendations': self._get_yield_improvement_tips(
                temp_factor, moisture_factor, nutrition_factor)
        }
    
    def _get_yield_improvement_tips(self, temp_factor: float, 
                                  moisture_factor: float, 
                                  nutrition_factor: float) -> List[str]:
        """获取增产建议"""
        tips = []
        
        if temp_factor < 1.0:
            tips.append("优化温度控制，使用遮阳网或保温设施")
        
        if moisture_factor < 1.0:
            tips.append("改善灌溉管理，保持土壤适宜湿度")
        
        if nutrition_factor < 1.0:
            tips.append("调节土壤pH值，优化养分配比")
        
        if not tips:
            tips.append("当前条件良好，继续保持精细化管理")
        
        return tips
    
    def generate_growth_trend_analysis(self, sensor_history: List) -> Dict:
        """生成生长趋势分析"""
        if len(sensor_history) < 7:
            return {'error': '数据不足，需要至少7天的历史数据'}
        
        # 分析最近7天的趋势
        recent_data = sensor_history[-7:]
        
        # 计算各参数的趋势
        trends = {}
        for param in ['soil_moisture', 'soil_temperature', 'air_temperature', 'ph_value']:
            values = [getattr(data, param) for data in recent_data]
            
            # 计算线性趋势
            x = np.arange(len(values))
            slope, intercept = np.polyfit(x, values, 1)
            
            trend_direction = "上升" if slope > 0.1 else "下降" if slope < -0.1 else "稳定"
            
            trends[param] = {
                'direction': trend_direction,
                'slope': slope,
                'current_value': values[-1],
                'average': np.mean(values),
                'stability': np.std(values)
            }
        
        # 生成分析报告
        analysis = {
            'period': '最近7天',
            'trends': trends,
            'overall_assessment': self._assess_overall_trend(trends),
            'recommendations': self._get_trend_recommendations(trends)
        }
        
        return analysis
    
    def _assess_overall_trend(self, trends: Dict) -> str:
        """评估整体趋势"""
        positive_trends = sum(1 for t in trends.values() if t['direction'] == '上升')
        negative_trends = sum(1 for t in trends.values() if t['direction'] == '下降')
        
        if positive_trends > negative_trends:
            return "整体向好"
        elif negative_trends > positive_trends:
            return "需要关注"
        else:
            return "基本稳定"
    
    def _get_trend_recommendations(self, trends: Dict) -> List[str]:
        """获取趋势建议"""
        recommendations = []
        
        soil_moisture_trend = trends.get('soil_moisture', {})
        if soil_moisture_trend.get('direction') == '下降':
            recommendations.append("土壤湿度呈下降趋势，建议增加灌溉频次")
        
        temp_trend = trends.get('air_temperature', {})
        if temp_trend.get('direction') == '上升' and temp_trend.get('current_value', 0) > 30:
            recommendations.append("温度持续上升，注意防护措施")
        
        ph_trend = trends.get('ph_value', {})
        if ph_trend.get('stability', 0) > 0.5:
            recommendations.append("pH值波动较大，建议检查施肥方案")
        
        if not recommendations:
            recommendations.append("各项指标趋势良好，继续保持当前管理策略")
        
        return recommendations